/*
	Analizador Sintactico
	Compilador C --
	Integrantes: Martinelli, Fernán Gabriel
		     Riberi, Franco Gaspar
		     Varea, Agustín	
*/

%{
#include <stdio.h>
#include <stdlib.h> /* Para usar el comando exit que permite cortar la ejecucion */
extern FILE *yyin;
extern int num_lineas;
%}

/* Declaración de los tokens definidos en el archivo lenguajeLex.l (flex) */
%token WHILE BREAK CONTINUE IF ELSE RETURN INT FLOAT  IGUALIGUAL AMPERAMPER  BARRABARRA  INTDENOTATION FLOATDENOTATION IDENTIFIER ERROR

/* Definición de mi simbolo inicial */
%start Program


/* Comienza la definición de la gramatica */

/* YYACCEPT corta la ejecucion de yyparse() haciendo que el mismo devuelva 0 */
/* para que no siga buscando cadenas siguientes y finalice la ejecución */

%%
 	
/* EXPRESIONES LOGICAS,MATEMATICAS Y RELACIONALES */
/* ESTRUCTURA DEL PROGRAMA */
Program : TypeSpecifier IDENTIFIER '(' declPar ')' Compound   			{ YYACCEPT; };
	
declPar : ParameterDecl ',' declPar | ParameterDecl ;

ParameterDecl : TypeSpecifier IDENTIFIER ;		

TypeSpecifier : INT | FLOAT ;

Compound : '{' cuerpo '}' ; 

cuerpo : var stat | ;

var : VariableDecl var | ;

stat : Statement stat | Statement;

VariableDecl : TypeSpecifier a ';' ;

a : IDENTIFIER b c ;

b : '=' Expression | ;		
 
c : ',' a| ;

Statement : Compound | Conditional | Iteration | w ';' ;

w : BREAK | CONTINUE | RETURN Expression | Computation | ;

Conditional : IF '(' Expression ')' Statement d ;

d : ELSE Statement | ;

Iteration : WHILE '(' Expression ')' Statement ;

Computation : Expression ;

Expression : IDENTIFIER '=' Expression 
	   | Condition 
	   ;

Condition : Disjunction
	  | Disjunction '?' Expression ':' Condition
	  ;

Disjunction : Conjunction
	    | Disjunction BARRABARRA Conjunction
	    ;

Conjunction : Comparison
	    | Conjunction AMPERAMPER Comparison
	    ;	

Comparison : Relation
	   | Relation IGUALIGUAL Relation
	   ;

Relation : Sum
	 | Sum '<' Sum
	 | Sum '>' Sum
	 ;

Sum : Term
    | Sum '+' Term
    | Sum '-' Term
    ;

Term : Factor
     | Term '*' Factor	
     | Term '/' Factor
     | Term '%' Factor
     ;

Factor : Primary
       | '!' Factor
       | '-' Factor
       ;

Primary : INTDENOTATION
	| FLOATDENOTATION 
	| IDENTIFIER
	| '(' Expression ')'
	;
%%
yywrap() 
{
	return 1;
}


/* Este metodo es llamado por yyparse si ocurre un error */
/* En caso de ocurra dicho error se ejecutara el cuerpo de este metodo*/
yyerror (char *a) 
{
  printf ("%s\n", a);
  printf ("%s", "ERROR EN LINEA: ");
  printf("%d\n",num_lineas ); 

}

/* Funcion que verifica si el nombre de un archivo es correcto. Es decir, solo tratamos archivos de extension .c-*/
int archivoValido(char* arch)  
{
   char*aux = arch;
   int f;
   int lenght =0;
   for (f=0; *arch != '\0'; f++) {
       lenght++;
      *arch++;
   }  
   int i = 0;	
   char c = aux[i];
   if (c != '.'){
      while (c != '.') {
         i++;
         c = aux[i]; 	
      }
      i++;
      c = aux[i];
      if (c == 'c') {
         i++;
         c = aux[i];
	 if (c == '-') {
	    i++;
	    c = aux[i];

	    if (i == lenght) {
		return 1;
   	    }else{
	       return 0;
	    }  
	 }else{
	    return 0;
	 }
      }else{
         return 0;
      }			     
   }else{
     return 0;
   }	 
}	

/* Si el archivo esta mal escrito, se posibilita volver a escribirlo, en caso de que no exista, se termina*/
main()
{
  char archivo[50];
  printf("Ingrese el archivo a compilar <nombreArchivo.c-> : "); 		
  scanf("%s",archivo);
  while (archivoValido(archivo) == 0) {
     printf("El archivo ingresado no es correcto \n");
     printf("Ingrese nuevamente <nombreArchivo.c-> : "); 		
     scanf("%s",archivo);
  }   
  yyin = fopen(archivo,"r");
  if (yyin == NULL) {
    printf("Su archivo no existe\n");
    printf("Ingrese nuevamente <nombreArchivo.c-> : "); 		
    scanf("%s",archivo);
    yyin = fopen(archivo,"r");
  }
  
  int c = yyparse(); 	  /* yyparse devuelve 0 en caso de finalizar el "parseo" con éxito */
  if(c == 0)
  {
    printf("COMPILACION EXITOSA\n");
    printf("Numero de lineas compiladas: ");
    printf("%d\n",num_lineas );
    printf("\n");
  }
  fclose(yyin);
}
